<script setup lang="ts">
import type { FormConfigModel } from '../shared'
import type { JSONResponse } from '@/api/json'
import { sendRequest } from '@/utils/api'
import sharedForm from '../sharedForm'
import { NScrollbar, useMessage } from 'naive-ui'
import { onMounted, ref } from 'vue'
import Axios from 'axios'

const props = defineProps<{
  active: string | null
  json: FormConfigModel[]
}>()

const emit = defineEmits<{
  (event: 'update:json', json: FormConfigModel[]): void
  (event: 'update:active', name: string | null): void
}>()

const message = useMessage()

const resetJsonId = (config: FormConfigModel[]) => {
  config.forEach((item) => {
    item.id = sharedForm.getUid()
    item.elements.forEach((element) => {
      element.id = sharedForm.getUid()
    })
  })
}

const handleUpdateActiveJsonName = (name: string) => {
  if (name === props.active) {
    emit('update:active', null)
    emit('update:json', [])
    return
  }
  emit('update:active', name)
  queryConfigJson(name)
}

const jsons = ref<string[]>([])
const queryConfigs = async () => {
  try {
    const [error, res] = await sendRequest<JSONResponse<string[]>>({
      module: 'json',
      api: 'list'
    })

    if (error) throw error
    if (res.code !== 200) throw new Error(res.message)
    jsons.value = res.data
  } catch (error) {
    if (error instanceof Error) message.error(error.message)
  }
}

let cancelToken = Axios.CancelToken.source()
const queryConfigJson = async (name: string) => {
  try {
    cancelToken.cancel()
    cancelToken = Axios.CancelToken.source()
    const [error, res] = await sendRequest<JSONResponse<FormConfigModel[]>>({
      module: 'json',
      api: 'content',
      override: {
        params: {
          name
        },
        cancelToken: cancelToken.token
      }
    })

    if (error) throw error
    if (res.code !== 200) throw new Error(res.message)
    resetJsonId(res.data)
    emit('update:json', res.data)
  } catch (error) {
    if (error instanceof Axios.Cancel) return
    if (error instanceof Error) message.error(error.message)
  }
}

const addFile = async (name: string) => {
  try {
    const [error, res] = await sendRequest<JSONResponse<string>>({
      module: 'json',
      api: 'save',
      override: {
        data: {
          name,
          data: []
        }
      }
    })

    if (error) throw error
    if (res.code !== 200) throw new Error(res.message)
    message.success('添加成功')
    queryConfigs()
  } catch (error) {
    if (error instanceof Error) message.error(error.message)
  }
}

const updateFile = async (name: string, data: FormConfigModel[]) => {
  try {
    const [error, res] = await sendRequest<JSONResponse<string>>({
      module: 'json',
      api: 'save',
      override: {
        data: {
          name,
          data
        }
      }
    })

    if (error) throw error
    if (res.code !== 200) throw new Error(res.message)
    message.success('更新成功')
    queryConfigs()
  } catch (error) {
    if (error instanceof Error) message.error(error.message)
  }
}

defineExpose({
  addFile,
  updateFile
})

onMounted(() => queryConfigs())
</script>

<template>
  <div class="form-configs">
    <NScrollbar style="max-height: 100%">
      <ul>
        <li
          v-for="(n, i) in jsons"
          :key="i"
          :class="{ active: n === active }"
          @click="handleUpdateActiveJsonName(n)"
        >
          {{ n }}
        </li>
      </ul>
    </NScrollbar>
  </div>
</template>

<style scoped>
.form-configs {
  width: 200px;
  padding: 10px;
}

ul {
  list-style: none;
}

li {
  color: #000;
  padding: 10px;
  background-color: #fff;
  margin-bottom: 10px;
  cursor: pointer;
  transition: all 0.15s ease-in-out;
}

li.active {
  background-color: #18a058;
  color: #fff;
}
</style>
